package fr.cephb.joperon.swing;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;


import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;

import fr.cephb.joperon.core.bio.Assembly;
import fr.cephb.joperon.core.bio.Chromosome;
import fr.cephb.joperon.core.db.SnpMapDB;
import fr.cephb.joperon.core.entities.SnpMap;
import fr.cephb.swing.GenericTableModel;
import fr.cephb.util.Cast;


/**
 * SnpMapFrame
 * @author lindenb
 *
 */
public class SnpMapFrame extends  OperonFrame
	{
	private static final long serialVersionUID = 1L;

	private static class Model
		extends GenericTableModel<SnpMap>
		{
		private static final long serialVersionUID = 1L;
		@Override
		public int getColumnCount() {
			return 5;
			}
		@Override
		public Object getValueOf(SnpMap item, int columnIndex) {
			switch(columnIndex)
				{
				case 0: return item.getAcn();
				case 1: return item.getChr();
				case 2: return item.getP();
				case 3: return item.getQ();
				case 4: return null;
				}
			return null;
			}
		}
	private Assembly assembly;
	private Model tableModel;
	private SimpleRegionRenderer render;
	private JTextField tfStart;
	private JTextField tfEnd;
	private JComboBox cbChrom;
	private JSpinner spinStart;
	private JSpinner spinCount;
	
	public SnpMapFrame(OperonGUI operon,Assembly assembly)
		{
		super(operon,"SnpMap : "+assembly.getName());
		this.assembly=assembly;
		
		JPanel top= new JPanel(new FlowLayout(FlowLayout.LEADING));
		super.content.add(top,BorderLayout.NORTH);
		top.add(new JLabel("Chrom:",JLabel.RIGHT));
		this.cbChrom = new JComboBox(Chromosome.values());
		top.add(this.cbChrom);
		top.add(new JLabel("Start:",JLabel.RIGHT));
		this.tfStart= new JTextField(10);
		top.add(this.tfStart);
		top.add(new JLabel("End:",JLabel.RIGHT));
		this.tfEnd = new JTextField(10);
		top.add(this.tfEnd);
		top.add(new JButton(new AbstractAction("OK")
			{
			private static final long serialVersionUID = 1L;
			@Override
			public void actionPerformed(ActionEvent e)
				{
				search();
				}
			}));
		top.add(new JLabel("From:",JLabel.RIGHT));
		this.spinStart= new JSpinner(new SpinnerNumberModel(0,0,Integer.MAX_VALUE,1));
		top.add(this.spinStart);
		top.add(new JLabel("Limit:",JLabel.RIGHT));
		this.spinCount = new JSpinner(new SpinnerNumberModel(1000,1,Integer.MAX_VALUE,1));
		top.add(this.spinCount);
		
		
		this.tableModel= new Model();
		JTable table= new JTable(this.tableModel);
		this.render= new SimpleRegionRenderer(2,3);
		table.getColumnModel().getColumn(4).setCellRenderer(this.render);
		super.content.add(new JScrollPane(table),BorderLayout.CENTER);
		}
	
	public Assembly getAssembly() {
		return assembly;
		}
	
	
	public void search()
		{
		if(this.cbChrom.getSelectedIndex()==-1) return;
		Chromosome chr= (Chromosome)cbChrom.getSelectedItem();
		if(!Cast.Integer.isA(tfStart.getText()) || !Cast.Integer.isA(tfEnd.getText()))
			{
			return ;
			}
		setPosition(chr,
				Cast.Integer.cast(tfStart.getText()),
				Cast.Integer.cast(tfEnd.getText())
				);
		}
	
	public void setPosition(Chromosome chrom,int start,int end)
		{
		SnpMapDB db1=null;
		this.tfStart.setText(String.valueOf(start));
		this.tfEnd.setText(String.valueOf(end));
		this.cbChrom.setSelectedItem(chrom);
		if(end<start) return;
		try {
			db1= new SnpMapDB(getOperon(),getAssembly());
			db1.open();
			SnpMapDB.ValueIterator iter=db1.listBetween(chrom, start, end);
			this.tableModel.removeAll();
			this.tableModel.addAll(iter.from(
				Number.class.cast(SpinnerNumberModel.class.cast(this.spinStart.getModel()).getValue()).intValue(),
				Number.class.cast(SpinnerNumberModel.class.cast(this.spinCount.getModel()).getValue()).intValue()
				).asList());
			
			long min=Long.MAX_VALUE;
			long max=0;
			for(int i=0;i< this.tableModel.getRowCount();++i)
				{
				min=Math.min( min,this.tableModel.elementAt(i).getP());
				max=Math.max( max,this.tableModel.elementAt(i).getQ());
				}
			this.render.setChromMin(min);
			this.render.setChromMax(max);
				
			
		} catch (Exception e)
			{
			JOptionPane.showMessageDialog(getOperonGUI(), e.getMessage());
			}
		finally
			{
			safeClose(db1);
			}
		}
	}
